﻿
/* $Id: NetServer.cs 9 2011-04-20 09:17:32Z nramsbottom@gmail.com $ */

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;

namespace SimpleNetServer
{

	class NetServer
	{

		private const int DefaultListenBacklog = 250;

		public IPAddress ListenAddress { get; private set; }
		public int ListenPort { get; private set; }

		private TcpListener _listener;

		private AsyncCallback _endAcceptCallback;

		private List<NetClient> _clients;

		public NetServer(IPAddress listenAddress, int listenPort)
		{

			this.ListenAddress = listenAddress;
			this.ListenPort = listenPort;

			_listener = new TcpListener(this.ListenAddress, this.ListenPort);
			_endAcceptCallback = new AsyncCallback(EndAccept);
			_clients = new List<NetClient>();

		} //

		public void Start()
		{
			_listener.Start(DefaultListenBacklog);
			BeginAccept();
		} //

		public void Stop()
		{
			// stop listening
			_listener.Stop();
			
			// disconnect existing clients
			lock(_clients)
			{
				while (_clients.Count > 0)
					_clients[0].Disconnect();
			}
			
		} //

		private void BeginAccept()
		{
			_listener.BeginAcceptSocket(_endAcceptCallback, null);
		} //

		private void EndAccept(IAsyncResult ar)
		{
			Socket accepted;

			try
			{
				accepted = _listener.EndAcceptSocket(ar);
			}
			catch (ObjectDisposedException ex)
			{
				return;
			}

			var client = new NetClient(accepted);

			client.Disconnected += OnClientDisconnected;

			OnClientConnected(client);

			BeginAccept();

		} //

		private void OnClientConnected(NetClient client)
		{
			Debug.WriteLine("Client connected.");
			_clients.Add(client);

			client.Send(new MotdResponsePacket("Welcome to the server."));

		} //

		private void OnClientDisconnected(NetClient client)
		{
			Debug.WriteLine("Client disconnected.");
			this._clients.Remove(client);
		} //

	} // class

} // namespace
